/*
 * Copyright (C) 2011 Roman "PlayeRom" Ludwicki
 *
 * Contact: tzm.android@gmail.com
 *
 * Licensed under the GNU General Public License, Version 3.0
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * 		http://www.gnu.org/licenses/gpl-3.0.txt
 */

package org.zeitgeist.movement.livewallpaper;

import java.util.Random;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.os.Handler;
import android.service.wallpaper.WallpaperService;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.WindowManager;

public class TZMLiveWallpaper extends WallpaperService {

	private final static String TAG = "TZMLiveWallpaper";

	@Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public Engine onCreateEngine() {
        return new TZMLiveWallpaperEngine();
    }

    public class TZMLiveWallpaperEngine extends Engine {
    	private final static int MAX_ANIM_FRAME = 419;
    	private final static int ANIM_FPS = 1000 / 40;

    	private final BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options();
    	private final Handler mHandler = new Handler();
    	private final Paint mPaint = new Paint();
    	private boolean mIsVisible;
    	private int mAnimCounter = 0;
    	private final String mText;
    	private int mSurfaceWidth;
    	private int mSurfaceHeight;
    	private int mXOffset;
    	private final int mTextWidth;
		private final int mTextHeight;

    	public TZMLiveWallpaperEngine() {
    		// random first frame of animation
    		final Random randomGenerator = new Random();
    		mAnimCounter = randomGenerator.nextInt(MAX_ANIM_FRAME - 1);

    		final DisplayMetrics displayMetrics = new DisplayMetrics();
    		final WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
    		wm.getDefaultDisplay().getMetrics(displayMetrics);

    		mPaint.setColor(0xffC8C8C8);
    		mPaint.setAntiAlias(true);
    		mPaint.setStrokeWidth(2);
    		mPaint.setStrokeCap(Paint.Cap.ROUND);
    		mPaint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
    		mPaint.setShadowLayer(1.2f, -1.5f, 1.5f, 0xff000000);
    		mPaint.setTextSize(getTextSize(displayMetrics.densityDpi));

    		mText = getString(R.string.text);
    		final Rect textBounds = new Rect();
    		mPaint.getTextBounds(mText, 0, mText.length(), textBounds);
    		mTextWidth = textBounds.right - textBounds.left;
			mTextHeight = textBounds.bottom - textBounds.top;

    		mBitmapOptions.inScreenDensity = displayMetrics.densityDpi;
    	}

    	@Override
    	public void onCreate(SurfaceHolder surfaceHolder) {
    		super.onCreate(surfaceHolder);

    		setTouchEventsEnabled(false);
    	}

    	@Override
    	public void onDestroy() {
    		super.onDestroy();

    		mHandler.removeCallbacks(mTaskDraw);
    	}

    	@Override
    	public void onVisibilityChanged(boolean visible) {
    		mIsVisible = visible;
    		if (visible) {
    			drawFrame();
    		}
    		else {
    			mHandler.removeCallbacks(mTaskDraw);
    		}
    	}

    	@Override
    	public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    		super.onSurfaceChanged(holder, format, width, height);

    		mSurfaceWidth = width;
    		mSurfaceHeight = height;

    	    drawFrame();
    	}

    	@Override
    	public void onSurfaceCreated(SurfaceHolder holder) {
    		super.onSurfaceCreated(holder);
    	}

    	@Override
    	public void onSurfaceDestroyed(SurfaceHolder holder) {
    		super.onSurfaceDestroyed(holder);

    		mIsVisible = false;
    		mHandler.removeCallbacks(mTaskDraw);
    	}

    	@Override
    	public void onOffsetsChanged(float xOffset, float yOffset, float xStep, float yStep, int xPixels, int yPixels) {
    		if (isPreview()) {
    			mXOffset = 0; // for preview mode without offset
    		}
    		else {
	    		mXOffset = xPixels + (mSurfaceWidth >> 1);

	    		//reduce the offset about half
	    		mXOffset >>= 1;
    		}

    		drawFrame();
    	}

    	/*
    	 * Store the position of the touch event so we can use it for drawing later
    	 */
    	/*@Override
    	public void onTouchEvent(MotionEvent event) {
    		if (event.getAction() == MotionEvent.ACTION_MOVE) {
    			mTouchX = event.getX();
    			mTouchY = event.getY();
    		}
    		else {
    			mTouchX = -1;
    			mTouchY = -1;
    		}

    		super.onTouchEvent(event);
    	}*/

    	private final Runnable mTaskDraw = new Runnable() {
    		public void run() {
    			drawFrame();
    		}
    	};

    	/**
    	 * Draw one frame of the animation. This method gets called repeatedly by posting a delayed Runnable.
    	 */
    	private void drawFrame() {
    		final SurfaceHolder holder = getSurfaceHolder();

    		Canvas canvas = null;
    		try {
    			canvas = holder.lockCanvas();
    			if (canvas != null) {
    				if (++mAnimCounter >= MAX_ANIM_FRAME)
    					mAnimCounter = 0;

    				// clear with black
    				canvas.drawColor(Color.BLACK);

    				// get current anim frame
    				final Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.frame00001 + mAnimCounter, mBitmapOptions);

    				final int bitmapWidth = bitmap.getWidth();
    				final int bitmapHeight = bitmap.getHeight();

    				final int xPosBmp = (((mSurfaceWidth - bitmapWidth) >> 1) + mXOffset);
    				final int yPosBmp = ((mSurfaceHeight - bitmapHeight) >> 1);

    				// draw frame
    				canvas.drawBitmap(bitmap,
    								  null,
    								  new Rect(xPosBmp, yPosBmp, bitmapWidth + xPosBmp, bitmapHeight + yPosBmp),
    								  null);

    				// draw text
    				canvas.drawText(mText,
    								((mSurfaceWidth - mTextWidth) >> 1) + mXOffset,
    								(mSurfaceHeight + (mTextHeight >> 1)) >> 1,
    								mPaint);
    			}
    		}
    		catch (Throwable th) {
    			final String str = th.toString();
    			if (str != null)
    				Log.e(TAG, str);
    		}
    		finally {
    			if (canvas != null)
    				holder.unlockCanvasAndPost(canvas);
    		}

    		// Reschedule the next redraw
    		mHandler.removeCallbacks(mTaskDraw);
    		if (mIsVisible) {
    			mHandler.postDelayed(mTaskDraw, ANIM_FPS);
    		}
    	}

    	/**
    	 * Get test size according to density of screen
    	 * @param densityDpi
    	 * @return
    	 */
    	private int getTextSize(final int densityDpi) {
    		switch (densityDpi) {
    			case DisplayMetrics.DENSITY_LOW:		return 18;
    			case DisplayMetrics.DENSITY_MEDIUM:		return 24;
    			case DisplayMetrics.DENSITY_HIGH:		return 35;
    			case DisplayMetrics.DENSITY_XHIGH:
    			default:				   				return 48;
    		}
    	}
    }
}